package dk.dtu.is.jjmvcp;
import jess.Context;
import jess.JessException;
import jess.Rete;
import jess.Userfunction;
import jess.Value;
import jess.ValueVector;
import dk.dtu.is.jjmvcp.controller.MyController;
import dk.dtu.is.jjmvcp.model.MyJavaBeanModel;
import dk.dtu.is.jjmvcp.view.MyView;


/**
 * This class is the wrapper of the entire MVC pattern and is used to pushed it into JESS. </br></br>
 * 
 * This is achieved by implementing the {@code UserFunction} interface of Jess, which enables to write 
 * a new function that can be used in JESS. </br></br>
 * 
 * The function name in JESS is the same of the name of this class and is defined through the public
 * method {@link #getName() getName()}. </br></br>
 * 
 * For further help, have a look at </br>
 * - section "12.1.1. Implementing your Userfunction" of Jess user manual</br>
 * - section "15.1 The Userfunction interface" of "Jess In Action"
 * 
 * @author dsac
 *
 */
public class addMVC implements Userfunction {
	
	/**
	 * The name that Jess will use to call this function
	 */
	private static final String functionName = "addMVC";
	
	// add the three view objects: the model, the view, the controller
	/**
	 * The reference to the model 
	 */
	private MyJavaBeanModel myJavaBeanModel;
	/**
	 * The reference to the view 
	 */
	private MyView myView;
	/**
	 * The reference to the controller
	 */
	private MyController myController;

	/**
	 * The code that will be run when Jess will call this Userfunction.</br></br>
	 * 
	 * It initializes the model, the view and the controller.</br>
	 * It also pushes the instance of the JavaBean into the defclass created in Jess
	 * 
	 * @return null
	 * @see jess.Userfunction#call(jess.ValueVector, jess.Context)
	 */
	@Override
	public Value call(ValueVector vv, Context context) throws JessException {
		
		// check the arguments
		if (vv.size() > 1) 
			throw new JessException(functionName,"Invalid number of arguments",vv.size() - 1);
		
		// get the current rete engine
		Rete rete = context.getEngine();
		
		// create the MVC
		// create the model - which is java bean
		myJavaBeanModel = new MyJavaBeanModel();
		// create the view - which is a MyView 
		myView = new MyView();
		// create the controller
		myController = new MyController();
		
		// add the model and the view to the current controller
		myController.addView(myView);
		myController.addModel(myJavaBeanModel);
		// and the controller to the view. I need this to add potential action listener to it.
		// and also add the model to the view. The view will update itself based upon property changes event on the model
		myView.addController(myController);
		myView.addModel(myJavaBeanModel);
		
		// add the current instance of the javabean into the template that has been created in JESS
		// N.B. we need to define the template in JESS because it needs to recognize it in the jess code.
		// 		If the template was defined with "rete.defclass("MyJavaBeanModel", "MyJavaBeanModel", null);" in the current
		//		java file, JESS would not know that it exists, and thus will throw error in the jess editor
		rete.definstance("MyJavaBeanModel", myJavaBeanModel, true);

		return null;
	}

	/** 
	 * It defines the name with which this UserFunction will be called in Jess
	 * 
	 * @return the name that will be used in {@code JESS} to call this function
	 * @see jess.Userfunction#getName()
	 */
	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return functionName;
	}
}